﻿using System.Collections.Generic;
using ClassMetadataBrowser.Domain;
using EnvDTE;
using System;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio;
using System.Runtime.InteropServices;
using IServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
using System.Windows.Forms;
using Thread = System.Threading.Thread;
using System.Threading;
using System.IO;
using EnvDTE80;
using ClassMetadataBrowser.ToolControls;
using System.Reflection;
using Gl.SettingsManager;
using ClassMedataBrowser.Domain;

namespace ClassMetadataBrowser
{
	public partial class Connect : INavigateToCodeElement
	{
		private const string DataSlotName = "classMetadataBrowserSlot";
		private SolutionFilesSettings _settings;

		public Connect() { }

		private MetadataController CurrectController
		{
			get
			{
				return Thread.GetData(Thread.GetNamedDataSlot(DataSlotName)) as MetadataController;
			}
		}

		private void ExecuteMemberSearchCommand()
		{
			Execute(FocusMode.MembersSearch);
		}

		private void ExecuteFileSearchCommand()
		{
			Execute(FocusMode.SolutionFileSearch);
		}

		private void Execute(FocusMode mode)
		{
			try
			{
				if (!_applicationObject.Solution.IsOpen)
					return;

				MetadataController provider = CurrectController;
				if (provider == null)
					provider = Init();

				ShowWindow(provider, mode, _applicationObject.ActiveDocument != null ? _applicationObject.ActiveDocument.Name : string.Empty);
			}
			catch (Exception ex)
			{
				// todo(0): implement logging
				MessageBox.Show(string.Format(Resources.InternalError, ex.ToString()),
					"VS Finder");
			}
		}

		private void ShowWindow(IMetadataProvider provider, FocusMode mode, string currentCaption)
		{
			if (mode == FocusMode.MembersSearch && _applicationObject.ActiveDocument == null)
				return;

			LoadSettings();
			HostWindow window = new HostWindow();
			window.Accept(provider, mode, _settings);

			if (mode == FocusMode.MembersSearch)
				window.Text = string.Format(Resources.Members, currentCaption);
		
			if (window.ShowDialog() == DialogResult.OK)
			{
				provider.ExecuteSelectionCommand();
				_applicationObject.ActiveDocument.Activate();
			}

			//HostControl control = null;

			//if (_window == null)
			//{
			//    // initializing new window
			//    string progId = Marshal.GenerateProgIdForType(typeof(HostControl));
			//    Windows2 windows = (Windows2)_applicationObject.Windows;
			//    Assembly currentAsm = Assembly.GetExecutingAssembly();

			//    object objControl = null;

			//    _window = (Window2)windows.CreateToolWindow2
			//        (
			//            _addInInstance,
			//            currentAsm.Location,
			//            typeof(HostControl).FullName,
			//            Resources.VsFinder,
			//            "{78666BE0-D7BB-4045-92C1-DCF19999C800}",
			//            ref objControl
			//        );

			//    _window.Visible = true;
			//    control = ((HostControl)_window.Object);
			//}
			//else
			//{
			//    _window.Visible = true;
			//    control = ((HostControl)_window.Object);
			//}

			//control.AcceptMetadataProvider(provider);
			//control.FileTitle = string.Format(Resources.Members, currentCaption);
		}

		#region Visual studio events

		private void SolutionClosing(ref bool fCancel)
		{
			//if (_window != null)
			//    _window.Close();
			try
			{
				MetadataController obj = (MetadataController)Thread.GetData(Thread.GetNamedDataSlot(DataSlotName));

				if (obj != null)
				{
					obj.AbortThread();
					obj.Dispose();
				}

			}
			catch (Exception ex)
			{
				// todo(0): implement logging
				MessageBox.Show(string.Format(Resources.InternalError, ex.ToString()),
					"VS Finder");
			}
		}

		private void SolutionEventsOpened()
		{
			Init();
		}

		private MetadataController Init()
		{
			MetadataController controller = new MetadataController(_applicationObject, this,
				_applicationObject.Events.get_WindowEvents(null));
			Thread.SetData(Thread.GetNamedDataSlot(DataSlotName), controller);
			controller.ActiveWindowChanged += new EventHandler(ActiveWindowChanged);
			return controller;
		}

		private void ActiveWindowChanged(object sender, EventArgs e) { }

		private void LoadSettings()
		{
			_settings = new SolutionFilesSettings();
			Settings.GetSettingsWithRegistryProvider().Load(_settings);
		}

		#endregion

		#region Working with the vs code editor

		#region INavigateToCodeElement Members

		void INavigateToCodeElement.Navigate(MetadataObjectBase obj)
		{
			Window window = obj.Element.ProjectItem.Open(Constants.vsViewKindCode);
			window.Activate();

			IVsTextView view = DTEUtils.GetTextCurrentTextView(_applicationObject);

			// skipping attributes lines
			int line = obj.Element.StartPoint.Line + obj.AttributesCount - 1;
			int column = obj.Element.StartPoint.LineCharOffset - 1;

			// getting text to determine length, because obj.Element.StartPoint.LineLength will give the length including attributes...
			string selectionText = string.Empty;
			view.GetTextStream(line, column, line, obj.Element.StartPoint.AbsoluteCharOffset, out selectionText);
			view.SetSelection(line, column, line, column + selectionText.Trim().Length);
		}

		#endregion

		#endregion
	}
}
